/***************************************************************
*  NAME:  digest_test
*	    
*  SYNOPSIS:  test for digest implementation
*    	    
*  DESCRIPTION:
*     	    
*  HISTORY:
*      	         pascal - Jan 22, 2012:  Created.
*
***************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "digest.h"

#define MD5_BLOCK_SIZE   64
#define MD5_INPUT_BLOCK_SIZE 56
#define MD5_RESULT_SIZE   4


struct s_md5_test {
  char * input;
  char * hash;
} md5_test[] =
{
  { "", "d41d8cd98f00b204e9800998ecf8427e" },
  {"a", "0cc175b9c0f1b6a831c399e269772661" },
  {"abc", "900150983cd24fb0d6963f7d28e17f72"},
  {"message digest", "f96b697d7cb7938d525a2f31aaf161d0"},
  {"abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b"},
  {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" ,"d174ab98d277d9f5a5611c2c9f419d9f" },
  {"12345678901234567890123456789012345678901234567890123456789012345678901234567890", "57edf4a22be3c955ac49da2e2107b67a"},
  {0, 0 }
};

#define MD5_STRINGSZ   ((MD5_RESULT_SIZE * 8) + 1)

void md5_tostr(unsigned char str [MD5_STRINGSZ],
	     unsigned int hash[MD5_RESULT_SIZE])
{
  unsigned char * p = (unsigned char*)hash;
  unsigned char * pstr = str;
  int k;

  // printf("sizeof hash = %d\n",sizeof(hash));
    
/*
  for (k=0; k < (MD5_RESULT_SIZE *4); k++, p++,pstr+=2) {
    sprintf(pstr,"%02x",*p);
    //printf("*p=%02x  pstr=%s\n",*p,str);
    }
*/

  for (k=0; k < MD5_RESULT_SIZE; k++,pstr+=8)
	  sprintf(pstr,"%08x",hash[k]);
  
}


void md5_print(unsigned int hash[MD5_RESULT_SIZE], int nl)
{
  unsigned char * p = (unsigned char*)hash;
  int k;
/*
  for (k=0; k < (MD5_RESULT_SIZE*4); k++, p++)
    printf("%02x",*p);
*/

    for (k=0; k < MD5_RESULT_SIZE; k++)
	    printf("%08x",hash[k]);

    
  if(nl) printf("\n");
}

void md5_validate()
{
  struct s_md5_test * p = md5_test;
  int ntest, nfail;
  //unsigned int hash[MD5_RESULT_SIZE];
  unsigned char md5str [MD5_STRINGSZ];
  int res;
  digest_ctx ctx;


		       
  ntest=0; nfail=0;

  for ( ; p->input; p++,ntest++) {
    
    int len = strlen(p->input);
    //md5_hash(p->input,len,hash);
    new_md5_digest(&ctx);	
    update_digest(&ctx, p->input, len);
    finalize_digest(&ctx);


    md5_tostr(md5str, ctx.hash);

    printf("Test %d\n",ntest);
    printf("Input (%s)\n",p->input);
    printf("MD5 expected: %s\n",p->hash);
    // printf("MD5 calcul. : "); md5_print(hash,1);
    printf("MD5 calcul. : %s\n",md5str);
    res=strcmp(p->hash,md5str);
    printf("result : %s\n",res ? "FAILED" : "OK");
    if (res) nfail++;
  }
  printf("%d tests/%d failed\n",ntest,nfail);
}




test_md5_main(int argc, char*argv[])
{
  int len;
  char * input;
  //unsigned int hash[MD5_RESULT_SIZE];
  digest_ctx ctx;

  new_md5_digest(&ctx);
  

  if (argc<2) {
    md5_validate();
    return;
  }
  input=argv[1];
  len=strlen(input);
  //md5_hash(input, len, hash);
  update_digest(&ctx, input, len);
  finalize_digest(&ctx);


  printf("sizeof int = %d, sizeof long = %d, sizeof long long = %d\n",sizeof(int),sizeof(long), sizeof(long long));

  printf("%s(%d): ",input,len);

  {
    unsigned char * p = (unsigned char*)&ctx.hash;
    int k;
    

    for (k=0; k < ctx.hash_len; k++, p++)
      printf("%02x",*p);
  }
    printf("\n");
}

#define SHA1_RESULT_SIZE 5


void sha1_print(unsigned int hash[SHA1_RESULT_SIZE], int nl)
{
  unsigned char * p = (unsigned char*)hash;
  int k;

  for (k=0; k < (SHA1_RESULT_SIZE*4); k++, p++)
	  printf("%02x",*p);

  printf("--> ");
  for (k=0; k < SHA1_RESULT_SIZE; k++)
	  printf("%08x ",hash[k]);
  

  if(nl) printf("\n");
}


sha1_test_main ()
{
  digest_ctx ctx;

  new_sha1_digest(&ctx);
  update_digest(&ctx, "abc", 3);
  finalize_digest(&ctx);

  sha1_print(ctx.hash,1);
}


main(int argc, char*argv[])
{
	test_md5_main(argc, argv);
	sha1_test_main();
}
